package com.attilax.vm;

import java.io.PrintStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import org.apache.commons.lang3.reflect.ConstructorUtils;

import com.attilax.c.CLibraryInterface;
import com.attilax.c.CRuntime;
import com.attilax.collection.AArrays;
import com.attilax.collection.ACollections;
import com.attilax.lang.AInt;
import com.attilax.math.ANum;
import com.attilax.ref.refx;
import com.attilax.reflect.MethodUtils;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

public class AtiVM {
	Object PCRegister;
	Cpu cpu;
	Stack stack = new Stack();
	Map Constant_pool = Maps.newConcurrentMap();

	public static void main(String[] args) {

		AtiVM vm = new AtiVM();
		vm.Constant_pool.put("#16", "Fieldref,#17.#19");
		vm.Constant_pool.put("#17", "Class,#18");
		vm.Constant_pool.put("#18", "Utf8,com/attilax/time/TimeJna$CLibrary");

		vm.getstatic(CRuntime.INSTANCE);// 获取指定类或者接口的静态域，并将其值压入栈顶
		vm.push(null); // 将null推送至栈顶
		vm.invokeinterface(CLibraryInterface.class, "time", 2);// 调用接口方法
																// ，从栈顶取出俩个数作为参数，把返回值放入栈顶

		vm.push(631123200);
		vm.sub();// sub 将栈顶两int型数值相减并将结果压入栈顶
		vm.push(850348800l);// 
		vm.cmp(); // cmp 比较栈顶两long型数值大小，并将结果（1，0，-1）压入栈顶
		if (vm.ifle()) // ifle 当栈顶int型数值小于等于0时跳转
		{
			vm.getstatic(System.out);    
			vm.push("ok");
			vm.invokevirtual(PrintStream.class, "println");  //调用实例方法
			vm.ret(); // return
		} else {
			// vm.new0(RuntimeException.class);
			 
			vm.push("ex1");
			vm.invokespecial(RuntimeException.class); // 调用超类构造方法，实例初始化方法，私有方法
			vm.athrow(); // 将栈顶的异常抛出
		}

		System.out.println("---finish");

	}

	// 调用超类构造方法，实例初始化方法，私有方法
	private void invokespecial(Class<?> class1) {
		Object[] params = VmUtil.pop2objArr(stack);
		try {
			Object o = ConstructorUtils.invokeConstructor(

			class1, params);
			stack.push(o);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}

	// 将栈顶的异常抛出
	private void athrow() {
System.out.println("--will throw");
		RuntimeException pop = (RuntimeException) stack.pop();
		throw pop;

	}

	private void ret() {
		// TODO Auto-generated method stub

	}

	private void getstatic(Object obj) {
		stack.push(obj);

	}
//调用实例方法
	private void invokevirtual(Class<?> class1, String meth) {

		Object[] arr=VmUtil.pop2objArr(stack);

		Object obj = arr[arr.length-1];
		Object[] params=new AArrays(arr).left(arr.length-1);
		try {
			Object ret = MethodUtils.invokeMethod(obj, meth, params);
			stack.push(ret);
		} catch (NoSuchMethodException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (IllegalAccessException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		} catch (InvocationTargetException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}

	}

	private void new0(Class<?> class1) {

	}

	private boolean ifle() {
		int num2 = (int) new ANum(stack.pop()).toInt();
		if (num2 <= 0)
			return true;
		else
			return false;

	}

	// 比较栈顶两long型数值大小，并将结果（1，0，-1）压入栈顶
	private void cmp() {
		Double num2 = new ANum(stack.pop()).toDouble();
		Double num1 = new ANum(stack.pop()).toDouble();
		if (num1 == num2)
			stack.push(0);
		if (num1 > num2)
			stack.push(1);
		if (num1 < num2)
			stack.push(-1);

	}

	// 将栈顶两int型数值相减并将结果压入栈顶
	private void sub() {
		Double num2 = new ANum(stack.pop()).toDouble();
		Double num1 = new ANum(stack.pop()).toDouble();
		Double numRet = num1 - num2;
		stack.push(numRet);

	}

	private void push(Object object) {
		stack.push(object);

	}

	@SuppressWarnings("all")
	private <ttx> void invokeinterface(Class<ttx> class1, String meth,
			int paramNum) {
		Object[] objs_tmp = VmUtil.pop2objArr(stack, paramNum);

		Object o = objs_tmp[paramNum - 1];

		Object[] params = AArrays.left(objs_tmp, paramNum - 1);

		ttx t = (ttx) o;
		// try {
		// Object ret = MethodUtils.invokeMethod(t, meth, params);
		// stack.push(ret);
		// } catch (NoSuchMethodException e1) {
		// // TODO Auto-generated catch block
		// e1.printStackTrace();
		// } catch (IllegalAccessException e1) {
		// // TODO Auto-generated catch block
		// e1.printStackTrace();
		// } catch (InvocationTargetException e1) {
		// // TODO Auto-generated catch block
		// e1.printStackTrace();
		// }
		try {
			Method m1 = refx.getMeth(class1, meth, params);
			Object ret = m1.invoke(o, params);
			stack.push(ret);
		} catch (SecurityException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (IllegalArgumentException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		} catch (InvocationTargetException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
			throw new RuntimeException(e);
		}

	}
 

}
